﻿// See https://aka.ms/new-console-template for more information
//Console.WriteLine("Hello, World!");

#region 单例模式
/*
//Singleton.GetInstance().GetId();
//Singleton.GetInstance().GetId();
//Singleton.GetInstance().GetId();

Parallel.For(0, 3, index =>
{
    var id = Singleton.GetInstance().GetId();
    Console.WriteLine("第{0}次：{1}", index, id);
});
class Singleton
{
    private Guid _guid;
    private static Singleton _instance;
    private static object _lock = new object();
    private Singleton()
    {
        _guid = Guid.NewGuid();
    }
    public static Singleton GetInstance()
    {
        if (_instance is null)//双判断加锁模式
        {
            lock (_lock)
            {
                if (_instance is null)
                {
                    _instance = new Singleton();
                }
            }
        }
        return _instance;
    }
    //public void GetId()
    //{
    //    Console.WriteLine(_guid);
    //}
    public Guid GetId()
    {
        //Console.WriteLine(_guid);
        return _guid;
    }
}
*/
#endregion
#region 策略模式

/*
 * 定义一系列的算法类，将每个算法分别封装起来，让他们可以相互替换
 */

/*
using Microsoft.Extensions.DependencyInjection;

//var ef = new EFcoreRepository();
//var redis = new RedisRepository();
//var appService = new AppService(redis);
//appService.Create(new object());

//依赖注入，IoC
var services = new ServiceCollection();
services.AddScoped<IRepository, EFcoreRepository>();
services.AddScoped<AppService>();
var buider = services.BuildServiceProvider();
var appService = buider.GetService<AppService>();
appService.Create(new object());
public interface IRepository
{
    void Add(object entity);
}
class AppService
{
    private readonly IRepository _repository;

    public AppService(IRepository repository)
    {
        _repository = repository;
    }
    public void Create(object entity)
    {
        _repository.Add(entity);
    }
}
public class EFcoreRepository : IRepository
{
    public void Add(object entity)
    {
        Console.WriteLine("EF core 仓储");
    }
}
public class RedisRepository : IRepository
{
    public void Add(object entity)
    {
        Console.WriteLine("Redis 仓储");
    }
}
*/

#endregion
#region 建造者模式
/*
//目的：上家定规范，下家来执行
Builder builder = new Elephent();
builder.Close();
abstract class Builder
{
    protected abstract void Step1();
    protected abstract void Step2();
    protected abstract void Step3();
    public void Close()
    {
        Step1();
        Step2();
        Step3();
    }
}
class Elephent : Builder
{
    protected override void Step1()
    {
        Console.WriteLine("把冰箱门打开");
    }

    protected override void Step2()
    {
        Console.WriteLine("把大象放进去");
    }

    protected override void Step3()
    {
        Console.WriteLine("把冰箱门关上");
    }
}
*/
#endregion
#region 抽象工厂三部曲
/* 简单工厂
using System.Data;

var factory = Factory.Create("SQL");
using (var conn = factory.GetConnection())
{
    conn.Open();
    ///
}

interface IDAO
{
    IDbConnection GetConnection();
}
class SqlServerDAO : IDAO
{
    public IDbConnection GetConnection()
    {
        throw new NotImplementedException();
    }
}
class MySqlDAO : IDAO
{
    public IDbConnection GetConnection()
    {
        throw new NotImplementedException();
    }
}
static class Factory
{
    public static IDAO Create(string name)
    {
        if (name.Equals("SQL"))
        {
            return new SqlServerDAO();
        }
        if (name.Equals("MySql"))
        {
            return new MySqlDAO();
        }
        throw new NotSupportedException();
    }
}
 */
/*

//工厂模式
using System.Data;

var factory = new SqlServerFactory();
var dao = factory.Cteate();
using (var conn = dao.GetConnection())
{
    conn.Open();
    ///
}

interface IDAO
{
    IDbConnection GetConnection();
}
class SqlServerDAO : IDAO
{
    public IDbConnection GetConnection()
    {
        throw new NotImplementedException();
    }
}
class MySqlDAO : IDAO
{
    public IDbConnection GetConnection()
    {
        throw new NotImplementedException();
    }
}
abstract class AbstractionFactory
{
    public abstract IDAO Cteate();
}
class SqlServerFactory : AbstractionFactory
{
    public override IDAO Cteate()
    {
        return new SqlServerDAO();
    }
}
class MySqlFactory : AbstractionFactory
{
    public override IDAO Cteate()
    {
        return new MySqlDAO();
    }
}
 */
//抽象工厂模式
/*
 * using System.Data;
var factory = new ERP();
var sql = factory.CreateSqlServer();
using (var con = sql.GetConnection())
{
    con.Open();
}
var mysql = factory.CreateMySql();
using (var con = mysql.GetConnection())
{
    con.Open();
}
interface IDAO
{
    IDbConnection GetConnection();
}
class SqlServerDAO : IDAO
{
    public IDbConnection GetConnection()
    {
        throw new NotImplementedException();
    }
}
class MySqlDAO : IDAO
{
    public IDbConnection GetConnection()
    {
        throw new NotImplementedException();
    }
}
abstract class AbsFactory
{
    public abstract IDAO CreateSqlServer();
    public abstract IDAO CreateMySql();
}
class ERP : AbsFactory
{
    public override IDAO CreateMySql()
    {
        return new MySqlDAO();
    }

    public override IDAO CreateSqlServer()
    {
        return new SqlServerDAO();
    }
}
 */

#endregion
#region 模板模式
/*
 * 
 var template = new MyTemplate2();
template.GetResult();
class MyTemplate : TemplateBase
{
    protected override void Step3()
    {
        Console.WriteLine("子类的步骤");
    }
}
class MyTemplate2 : TemplateBase
{
    protected override void Step3()
    {
        Console.WriteLine("子类的步骤");
    }
    protected override void Step4()
    {
        Console.WriteLine("心情不好，想重写");
    }
}
abstract class TemplateBase
{
    void Step1()
    {
        Console.WriteLine("步骤1");
    }
    void Step2()
    {
        Console.WriteLine("步骤2");
    }
    protected abstract void Step3();
    protected virtual void Step4()
    {
        Console.WriteLine("步骤4");
    }
    public void GetResult()
    {
        Step1();
        Step2();
        Step3();
        Step4();
    }
}*
 */

#endregion
#region 外观模式
/*
 * Facade facade = new Facade();
var authuroties = facade.GetUserAuthorities(1);
interface IUserRepository
{
    object GetById(in int id);//in指定参数是只读的，可以提高新能
}
interface IRoleRepository
{
    IEnumerable<string> GetRoles(in int userId);
}
interface IAuthorityRepository
{
    IEnumerable<string> GetAuthorities(IEnumerable<string> roles);
}
class Facade
{
    private readonly IUserRepository _userRepository;
    private readonly IAuthorityRepository _authorityRepository;
    private readonly IRoleRepository _roleRepository;
    public Facade()
    {
        
    }
    public IEnumerable<string> GetUserAuthorities(in int userId)
    {
        var user = _userRepository.GetById(userId);
        var roles = _roleRepository.GetRoles(userId);
        var authorities = _authorityRepository.GetAuthorities(roles);
        return authorities;
    }
}
 */

#endregion
#region 中介者模式
//由中间者来负责对接双方的交互
/*
 * 
 var landload = new User("房东");
var tenant = new User("房客");
Mediator mediator = new Mediator();
mediator.Trade(1000, landload, tenant);
class User
{
    public User(string name)
    {
        Name = name;
    }
    public string Name { get; }
    public int Amount { get; set; }
}
class Mediator
{
    public void Trade(int amount,User user1,User user2)
    {
        user1.Amount += amount;
        user2.Amount -= amount;
        Console.WriteLine("{0}增加了{1}元，结余：{2}", user1.Name, amount, user1.Amount);
        Console.WriteLine("{0}增加了{1}元，结余：{2}", user2.Name, amount, user2.Amount);
    }
} 
 */
/*
var service = new UserRoleService();
var user = new User();
var role = new Role();
service.AssignRole(user, role);
class User { }
class Role { }
class UserInRole
{
    public User User { get; set; }
    public Role Role { get; set; }
}
class UserRoleService
{
    public void AssignRole(User user,Role role)
    {
        new UserInRole() { User = user, Role = role};
    }
}
 */

#endregion
#region 适配器模式
/*将一个类的接口转换成客户希望的另外一个接口，
 * 使得原来由于接口不兼容而不能一起工作的那些类可以一起工作。
 */
/*
 IExpectedInterface client = new ExistObj();
Console.WriteLine(client.Name);
var adpter = new Adapter();
client = adpter;
Console.WriteLine(client.Name);
interface IExpectedInterface
{
    public string Name { get; set; }
}
class ExistObj : IExpectedInterface
{
    public string Name { get; set; } = "已经存在";
}
class YourClass
{
    public DateTime Birthday { get; set; } = DateTime.Now;
}
class Adapter : YourClass, IExpectedInterface
{
    public string Name { get; set; }
    public Adapter()
    {
        Name = Birthday.ToString();
    }
}
 */

#endregion
#region 观察者模式
/*目的：让下面的对象一致的行动
 */
/*
Teacher teacher = new Teacher();
teacher.Add(new Action1());
teacher.Add(new Action2());
teacher.Command();
interface IAction
{
    void Do();
}
class Action1 : IAction
{
    public void Do() => Console.WriteLine("Action1 做了行为");
}
class Action2 : IAction
{
    public void Do() => Console.WriteLine("Action2  做了行了");
}
class Teacher
{
    List<IAction> Actions = new List<IAction>();
    public void Add(IAction action)
    {
        Actions.Add(action);
    }
    public void Remove(IAction action)
    {
        Actions.Remove(action);
    }
    public void Command()
    {
        Actions.ForEach(action => action.Do());
    }
} 
 */

#endregion
#region 享元模式
/*
 //缓存
CacheManager cacheManager = new();
var value1 = cacheManager.GetOrCreat<Operation1>("key",() => new() { Name = "Init"});
Console.WriteLine(value1.Name);
var value2 = cacheManager.GetOrCreat<Operation1>("key");
Console.WriteLine(value2.Name);
interface IOperation
{
    string Name { get; set; }
}
class Operation1 : IOperation
{
    public string Name { get; set; }
}
class CacheManager
{
    private static Dictionary<string, IOperation> _operations = new();
    public IOperation GetOrCreat<T>(string key, Func<T>? func = default)
        where T : IOperation, new()//约束
    {
        if (!_operations.ContainsKey(key))
        {
            _operations.Add(key, func is null ? new T() : func());
        }
        return _operations[key];
    }
}
 */

#endregion
#region 桥接模式
/*
//目的：双方独立，且又能关联
using Microsoft.EntityFrameworkCore;
var repository = new EFRepository<User>(new MyDbContext());
repository.Add(new User { Id = 1 });
class User
{
    public int Id { get; set; }
}
class MyDbContext : DbContext
{
    
}
interface IRepository<TEntity> where TEntity : class
{
    void Add(TEntity entity);
    void Remove(TEntity entity);
}
class EFRepository<TEntity> : IRepository<TEntity> where TEntity : class
{
    private readonly DbContext _context;

    public EFRepository(DbContext context)
    {
        _context = context;
    }
    public void Add(TEntity entity)
    {
        _context.Add(entity);
    }

    public void Remove(TEntity entity)
    {
        _context.Remove(entity);
    }
} 
 */

#endregion
#region 迭代器模式
/*
//目的：循环便利输出结果
var users = new List<User>() 
{
    new(){ Name = "张三"},
    new(){ Name = "李四"},
    new(){ Name = "王五"},
    new(){ Name = "赵六"}
};
var collection = new UserCollection(users.ToArray());
while (collection.HasNext())
{
    var user = (User)collection.Next();
    Console.WriteLine(user.Name);
}
class User
{
    public string Name { get; set; }
}
interface IIterator
{
    bool HasNext();
    object Next();
}
class UserCollection : IIterator
{
    User[] _users;
    int index = 0;
    public UserCollection(User[] users)
    {
        _users = users;
    }
    public bool HasNext()
    {
        return index < _users.Length;
    }

    public object Next()
    {
        var instance = _users[index++];
        return instance;
    }
} 
 */
/*
using System.Collections;

var users = new List<User>()
{
    new(){ Name = "张三"},
    new(){ Name = "李四"},
    new(){ Name = "王五"},
    new(){ Name = "赵六"}
};
var collection = new UserCollection(users.ToArray());
while (collection.MoveNext())
{
    var user = (User)collection.Current;
    Console.WriteLine(user.Name);
}
class User
{
    public string Name { get; set; }
}
interface IIterator
{
    bool HasNext();
    object Next();
}
class UserCollection : IEnumerator
{
    User[] _users;
    int index = -1;
    public object Current { get; private set; }
    public UserCollection(User[] users)
    {
        _users = users;
    }

    public bool MoveNext()
    {
        index++;
        Current = _users[index];
        return index < _users.Length - 1;
    }

    public void Reset()
    {
        index = -1;
    }
} 
 */

#endregion
#region 装饰器模式
/*
//目的：重用功能并增加新功能
new Anchor().Inner();
Console.WriteLine();
new Bold(new Anchor()).Inner();
Console.WriteLine();
new Italic(new Bold(new Anchor())).Inner();
Console.WriteLine("\n\n");

new Paragraph().Inner();
Console.WriteLine();
new Bold(new Paragraph()).Inner();
Console.WriteLine();
new Italic(new Bold(new Paragraph())).Inner();
Console.WriteLine();
Console.ReadKey();
abstract class HtmlElement
{
    protected internal abstract void Inner();
    protected abstract string TagName { get; }
}
class Anchor : HtmlElement
{
    protected override string TagName => "a";

    protected internal override void Inner()
    {
        Console.Write("<{0}>Anchor</{0}>", TagName);
    }
}
class Paragraph : HtmlElement
{
    protected override string TagName => "p";

    protected internal override void Inner()
    {
        Console.Write("<{0}>Paragraph</{0}>", TagName);
    }
}
abstract class Decorator : HtmlElement
{
    private readonly HtmlElement _element;

    public Decorator(HtmlElement element)
    {
        _element = element;
    }
    protected internal override void Inner() 
    {
        Console.Write($"<{TagName}>");
        _element.Inner();
        Console.Write($"</{TagName}>");
    }
}
class Bold : Decorator
{
    public Bold(HtmlElement element) : base(element)
    {

    }

    protected override string TagName => "b";
}
class Italic : Decorator
{
    public Italic(HtmlElement element) : base(element)
    {

    }

    protected override string TagName => "i";
}
 */

#endregion
#region 代理模式
/*
//目的：帮你完成你没有完成的内容
var real = new RealAction();
var proxy = new ProxyAction(real);
proxy.Do();
interface IAction
{
    void Do();
}
class RealAction : IAction
{
    public void Do() => Console.WriteLine("我是真的");
}
class ProxyAction : IAction
{
    private readonly IAction _action;

    public ProxyAction(IAction action)
    {
        _action = action;
    }
    public void Do()
    {
        Console.WriteLine("我在真的之前");
        _action.Do();
        Console.WriteLine("我在真的之后");
    }
}
 */

#endregion
#region 责任链模式
/*
//目的：层层传递，层层处理
var context = new ProcessContext();
var manager = new ProcessA();
var leader = new ProcessB();
var director = new ProcessC();
leader.Next = director;
director.Next = manager;
leader.Process(context);
class ProcessContext
{
    public string Name { get; set; }
}
abstract class ProcessHandler
{
    public ProcessHandler Next { get; set; }
    public abstract void Process(ProcessContext context);
}
class ProcessA : ProcessHandler
{
    public override void Process(ProcessContext context)
    {
        context.Name = "领导";
        Console.WriteLine("流程 A,{0}处理", context.Name);
        Next?.Process(context);
    }
}
class ProcessB : ProcessHandler
{
    public override void Process(ProcessContext context)
    {
        context.Name = "主管处理";
        Console.WriteLine("流程 B,{0}处理", context.Name);
        Next?.Process(context);
    }
}
class ProcessC : ProcessHandler
{
    public override void Process(ProcessContext context)
    {
        context.Name = "总监处理";
        Console.WriteLine("流程 C,{0}处理", context.Name);
        Next?.Process(context);
    }
} 
 */

#endregion
#region 过滤器模式
/*
var list = Enumerable.Range(1, 1000);
FilterA filterA = new();
FilterB filterB = new();
list = filterA.Filter(list);
list = filterB.Filter(list);
foreach (var item in list)
{
    Console.WriteLine(item);
}
interface IFilter
{
    IEnumerable<int> Filter(IEnumerable<int> list);
}
class FilterA : IFilter
{
    public IEnumerable<int> Filter(IEnumerable<int> list)
    {
        if (list.Sum() > 100)
        {
            Console.WriteLine("超过了100");
            list  = list.Skip(10).ToList();
        }
        return list;
    }
}
class FilterB : IFilter
{
    public IEnumerable<int> Filter(IEnumerable<int> list)
    {
        if (list.Count() > 40)
        {
            list = list.Take(10).ToList();
        }
        return list;
    }
} 
 */

#endregion
#region 组合模式
/*
//目的：这就是一棵树。。。
using System.Text;
Node node = new()
{
    Name = "根",
    Children = new List<Node>()
    {
        new(){ Name = "子节点1"},
        new(){ 
            Name = "子节点2",
            Children = new List<Node>()
            {
                new(){ Name = "第二个子节点"}
            }
        }
    }
};
Console.WriteLine(node);

class Node
{
    public string Name { get; set; }
    public ICollection<Node> Children { get; set;} = new HashSet<Node>();
    public override string ToString()
    {
        var buider = new StringBuilder();
        buider.Append(Name);
        buider.AppendLine();
        Loop(buider, Children, 1);
        return buider.ToString();
    }
    void Loop(StringBuilder builder,IEnumerable<Node> nodes,int deep)
    {
        foreach (var child in nodes)
        {
            builder.AppendFormat("|{0}{1}",new string('-',deep), child.Name);
            builder.AppendLine();
            deep++;
            Loop(builder, child.Children, deep);
        }
    }
}
 */

#endregion
#region 备忘录模式
/*
//目的：保存历史记录，随时恢复
var history = new History();
var user = new User { Name = "第一次记录"};
history.Add(user.Save());
user.Name = "修改了值";
history.Add(user.Save());
user.Name = "第三次修改";
history.Add(user.Save());

Console.WriteLine("获得第二次修改：{0}",history.Get(1).User.Name);
Console.WriteLine("获得第一次修改：{0}", history.Get(0).User.Name);

class User
{
    public string Name { get; set; }
    public Momento Save() => new(new() { Name = Name});
    public User Restor(Momento momento) => momento.User;
}
class Momento
{
    public Momento(User user)
    {
        this.User = user;
    }
    public User User { get; set; }
}
class History
{
    List<Momento> Momentos { get; set; } = new();
    public void Add(Momento momento) => Momentos.Add(momento);
    public Momento Get(int version) => Momentos[version];
}
 */

#endregion
#region 命令模式
var person = new Person();
var command = new WashCommand(person);
command.Execute();
class Person
{
    internal void WashHand()
    {
        Console.WriteLine("洗了个手");
    }
}
interface ICommand
{
    void Execute();
}
class WashCommand : ICommand
{
    private readonly Person _person;

    public WashCommand(Person person)
    {
          _person  = person;
    }
    public void Execute()
    {
        _person.WashHand();
    }
}
#endregion